#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <check.h>

#include "file_db.h"

/* TODO

 - check that if partial doesn't exist, file_db_create doesn't fail
 - check that get_complete_files doesn't fail if there's no file to list

 */

file_db *db;

void setup (void);
void teardown (void);

/*
 * Tests de creación
 */
START_TEST (test_invalid_path)
{
    file_db *db = NULL ;
    db = file_db_create (NULL);
}
END_TEST

START_TEST (test_inexistent_path)
{
    file_db *db = NULL ;
    db = file_db_create ("/does not exist");
}
END_TEST

START_TEST (test_not_a_directory)
{
    file_db *db = NULL ;
    db = file_db_create ("Makefile");
}
END_TEST

/*
 * Tests de funcionalidad
 */

#define TEST_DIR "downloads"

void setup (void)
{
    int error = 0;

    error = system ("rm -rf " TEST_DIR);
    assert (error==0);
    error = mkdir (TEST_DIR, 0777);
    assert (error==0);
    error = mkdir (TEST_DIR "/partial", 0777);
    assert (error==0);

    db = file_db_create ("downloads");
}

void teardown (void)
{
    file_db_destroy (db);
    system ("rm -rf " TEST_DIR);
}

START_TEST (test_created_properly)
{
    fail_unless (db != NULL, "file db not created");
}
END_TEST

START_TEST (test_create_empty_file)
{
    struct stat info;
    int error = 0;
    file *result = NULL;

    result = create_file (
        db,
        "d41d8cd98f00b204e9800998ecf8427e", /* md5("") */
        "empty",
        0
    );
    error = stat (TEST_DIR "/partial/d41d8cd98f00b204e9800998ecf8427e.empty", &info);
    fail_if (error, "error on stat");
    fail_unless (info.st_size==0, "File should be empty");
}
END_TEST

START_TEST (test_empty_file_properties)
{
    file *result = NULL;

    result = create_file (
        db,
        "d41d8cd98f00b204e9800998ecf8427e", /* md5("") */
        "empty",
        0
    );
    fail_unless (result != NULL, "No file returned");
    fail_unless (file_is_partial (result), "File is not partial");
    fail_unless (! file_has_index_info (result), "File should not have index_info");
    fail_unless (file_fragment_count (result) == 0, "File should have 0 fragments");
    fail_unless (file_size (result) == 0, "File should have 0 bytes");
    fail_unless (strcmp (file_name (result), "empty") == 0, "File should be named 'empty'");
}
END_TEST

/* Armado de la test suite */

Suite *db_suite (void);

Suite *db_suite (void)
{
    Suite *s = suite_create ("File DB");

    TCase *tc_creation = tcase_create ("Creation");
    TCase *tc_function = tcase_create ("Function");

    /* Creación */
    tcase_add_test_raise_signal (tc_creation, test_invalid_path, SIGABRT);
    tcase_add_test_raise_signal (tc_creation, test_inexistent_path, SIGABRT);
    tcase_add_test_raise_signal (tc_creation, test_not_a_directory, SIGABRT);
    suite_add_tcase (s, tc_creation);

    /* Funcionalidad */
    tcase_add_checked_fixture (tc_function, setup, teardown);
    tcase_add_test (tc_function, test_created_properly);
    tcase_add_test (tc_function, test_create_empty_file);
    tcase_add_test (tc_function, test_empty_file_properties);
    suite_add_tcase (s, tc_function);

    return s;
}

int main (void)
{
    int number_failed;
    Suite *s = db_suite ();
    SRunner *sr = srunner_create (s);
    srunner_run_all (sr, CK_VERBOSE);
    number_failed = srunner_ntests_failed (sr);
    srunner_free (sr);
    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
